use std::{rc::Rc, cell::RefCell};

use crate::classfile::LineNumberTableAttribute;

use super::{ConstantPool, AttributeInfo, ClassReader, Attribute};

// Java程序方法体里面的代码经过Javac编译器处理之后，最终变为字节码指令存储在Code属性内。
// Code属性出现在方法表的属性集合之中，但并非所有的方法表都必须存在这个属性，譬如接口或者抽
// 象类中的方法就不存在Code属性

// Code属性是method_info结构（§4.6）的属性表中的可变长度属性。
// Code属性包含Java虚拟机指令和方法的辅助信息，包括实例初始化方法或类或接口初始化方法（§2.9）。

// Code_attribute {
// u2 attribute_name_index; //指向CONSTANT_Utf8_info型常量池索引，此时名称固定为 "Code"
// u4 attribute_length; // 总长度, 不包括attribute_name_index与attribute_length所占的六个字节
// u2 max_stack; // 操作数栈（Operand Stack）最大深度，Javac编译器计算出
// u2 max_locals; // 局部变量表（Local Vars）的大小，Javac编译器计算出
// u4 code_length; // 字节码长度，《Java虚拟机规范》中明确限制了一个方法不允许超过65535条字节码指令，实际使用u2长度
// u1 code[code_length]; // 字节码指令
// u2 exception_table_length; //异常表长度（个数）
// {   u2 start_pc;
//     u2 end_pc;
//     u2 handler_pc;
//     u2 catch_type;
// } exception_table[exception_table_length]; // 异常表
// u2 attributes_count; //属性数
// attribute_info attributes[attributes_count]; // 属性
// }

// 在任何实例方法里面，都可以通过“this”关键字访问到此方法所属的对象。声明为static就不行了

// Code属性
pub struct CodeAttribute {
    cp: Rc<RefCell<ConstantPool>>,
    max_stack: u16,
    max_locals: u16,
    code: Vec<u8>,
    exception_table: Vec<ExceptionTableEntry>,
    attributes: Vec<Attribute>
}

impl AttributeInfo for CodeAttribute {
    // 从classreader读取
    fn read_info(&mut self, reader: &mut ClassReader) {
        self.max_stack = reader.read_u16();
        self.max_locals = reader.read_u16();
        let code_length = reader.read_u32() as usize;
        self.code = reader.read_bytes(code_length);
        self.exception_table = ExceptionTableEntry::read_exception_table(reader);
        self.attributes = super::read_attributes(reader, self.cp.clone())
    }
}

impl CodeAttribute {
    pub fn new(cp: Rc<RefCell<ConstantPool>>) -> CodeAttribute {
        CodeAttribute { 
            cp, 
            max_stack: u16::default(), 
            max_locals: u16::default(), 
            code: vec![], 
            exception_table: vec![], 
            attributes: vec![] 
        }
    }

    pub fn get_max_locals(&self) -> u16 {
        self.max_locals
    }

    pub fn get_max_stack(&self) -> u16 {
        self.max_stack
    }

    pub fn get_code(&self) -> &Vec<u8> {
        &self.code
    }

    pub fn get_exception_table(&self) -> &Vec<ExceptionTableEntry> {
        &self.exception_table
    }

    pub fn line_number_table_attribute(&self) -> Option<LineNumberTableAttribute> {
        for attr_info in &self.attributes {
            if let Attribute::LineNumberTableAttribute(info) = attr_info {
                return Some(info.clone());
            }
        }
        None
    }
}


// 如果当字节码从第start_pc行[1]到第end_pc行之间（不含第end_pc行）出现了类型为catch_type或者其子类的异常
//（catch_type为指向一个CONSTANT_Class_info型常量的索引），则转到第handler_pc行继续处理。
// 当catch_type的值为0时，代表任意异常情况都需要转到handler_pc处进行处理。
// 异常表，可以被catch处理的异常
pub struct ExceptionTableEntry {
    pub start_pc: u16,
    pub end_pc: u16,
    pub handler_pc: u16,
    pub catch_type: u16
}

impl ExceptionTableEntry {
    // 读取异常表
    pub fn read_exception_table(reader: &mut ClassReader) -> Vec<ExceptionTableEntry> {
        let exception_table_length = reader.read_u16();
        let mut exception_table = vec![];
        for _ in 0..exception_table_length {
            exception_table.push(
                ExceptionTableEntry { 
                    start_pc: reader.read_u16(), 
                    end_pc: reader.read_u16(), 
                    handler_pc: reader.read_u16(), 
                    catch_type: reader.read_u16() 
                }
            )
        }
        exception_table
    }
}

